package io.youngledo.usb.license;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.time.LocalDateTime;
import java.util.List;

/// 许可证数据模型
///
/// 使用 Java Record 定义不可变的许可证数据结构。
/// 许可证文件包含以下信息：
/// - 许可证类型和用户信息
/// - 有效期和启用的功能
/// - RSA签名（用于验证真实性）
///
/// ## 许可证文件格式（JSON）
/// ```json
/// {
///   "licenseKey": "XXXX-XXXX-XXXX-XXXX",
///   "type": "PROFESSIONAL",
///   "userId": "user@example.com",
///   "userName": "张三",
///   "issuedAt": "2025-01-01T00:00:00",
///   "expiryDate": "2026-01-01T00:00:00",
///   "machineId": "MACHINE-ID-HASH",
///   "enabledFeatures": ["BATCH_OPERATIONS", "TASK_MANAGEMENT"],
///   "signature": "BASE64-ENCODED-RSA-SIGNATURE"
/// }
/// ```
@JsonIgnoreProperties(ignoreUnknown = true)
public record License(
        /// 许可证密钥（格式：XXXX-XXXX-XXXX-XXXX）
        @JsonProperty("licenseKey")
        String licenseKey,

        /// 许可证类型
        @JsonProperty("type")
        LicenseType type,

        /// 用户ID（通常是邮箱）
        @JsonProperty("userId")
        String userId,

        /// 用户名称
        @JsonProperty("userName")
        String userName,

        /// 签发时间
        @JsonProperty("issuedAt")
        LocalDateTime issuedAt,

        /// 到期时间（null表示永久有效）
        @JsonProperty("expiryDate")
        LocalDateTime expiryDate,

        /// 机器ID（可选，用于绑定设备）
        @JsonProperty("machineId")
        String machineId,

        /// 启用的功能列表
        @JsonProperty("enabledFeatures")
        List<Feature> enabledFeatures,

        /// RSA签名（Base64编码）
        @JsonProperty("signature")
        String signature
) {
    /// 判断许可证是否已过期
    ///
    /// @return 如果许可证已过期返回true，永久许可证返回false
    public boolean isExpired() {
        return expiryDate != null && LocalDateTime.now().isAfter(expiryDate);
    }

    /// 判断许可证是否有效
    ///
    /// @return 如果许可证未过期且签名有效返回true
    public boolean isValid() {
        return !isExpired();
    }

    /// 判断是否启用了指定功能
    ///
    /// @param feature 要检查的功能
    /// @return 如果该功能在启用列表中返回true
    public boolean hasFeature(Feature feature) {
        return enabledFeatures != null && enabledFeatures.contains(feature);
    }

    /// 获取许可证的显示信息
    ///
    /// @return 格式化的许可证信息字符串
    public String getDisplayInfo() {
        var expiryInfo = expiryDate == null ? "永久有效" : "到期时间: " + expiryDate;
        return """
                许可证类型: %s
                用户: %s (%s)
                %s
                启用功能数: %d
                """.formatted(
                type.getDisplayName(),
                userName,
                userId,
                expiryInfo,
                enabledFeatures != null ? enabledFeatures.size() : 0
        );
    }

    /// 获取用于签名的数据字符串
    ///
    /// 将许可证的关键字段拼接成字符串，用于RSA签名和验证。
    /// **注意**: signature字段不参与签名计算
    ///
    /// @return 用于签名的数据字符串
    public String getDataForSignature() {
        return String.format("%s|%s|%s|%s|%s|%s|%s|%s",
                licenseKey,
                type,
                userId,
                userName,
                issuedAt,
                expiryDate,
                machineId,
                enabledFeatures
        );
    }

    /// 创建社区版许可证（默认免费许可证）
    ///
    /// @return 永久有效的社区版许可证
    public static License createCommunityLicense() {
        return new License(
                "COMMUNITY-FREE-LICENSE",
                LicenseType.COMMUNITY,
                "community@user",
                "社区版用户",
                LocalDateTime.now(),
                null, // 永久有效
                null, // 不绑定机器
                List.of(), // 社区版没有专业功能
                "" // 无需签名
        );
    }
}
